package com.jsjosem.aftersales.ui.worktickets;

import static com.jsjosem.aftersales.utils.CommonUtils.getInstalledAppList;
import static com.jsjosem.aftersales.utils.CommonUtils.startNavi;

import android.app.Dialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;

import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.gson.Gson;
import com.jsjosem.aftersales.R;
import com.jsjosem.aftersales.adapter.StateAdapter;
import com.jsjosem.aftersales.api.RetrofitClient;
import com.jsjosem.aftersales.api.WorkOrderApi;
import com.jsjosem.aftersales.component.ConfirmDialog;
import com.jsjosem.aftersales.component.DrawableHorizontalButton;
import com.jsjosem.aftersales.component.NodeProcessBar;
import com.jsjosem.aftersales.component.SelectDateDialog;
import com.jsjosem.aftersales.data.model.AppInfo;
import com.jsjosem.aftersales.data.request.AcceptWorkOrderRequest;
import com.jsjosem.aftersales.data.response.BaseResponse;
import com.jsjosem.aftersales.data.response.OperationLogResponse;
import com.jsjosem.aftersales.data.response.UserInfoResponse;
import com.jsjosem.aftersales.data.response.WorkOrderHistoryResponse;
import com.jsjosem.aftersales.data.response.WorkOrderResponse;
import com.jsjosem.aftersales.data.response.WorkTicket;
import com.jsjosem.aftersales.databinding.ActivityWorkTicketsInfoBinding;
import com.jsjosem.aftersales.enums.WorkOrderStatusEnum;
import com.jsjosem.aftersales.request.AsyncRequest;
import com.jsjosem.aftersales.utils.ViewUtils;
import com.wang.avi.AVLoadingIndicatorView;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import retrofit2.Call;
import retrofit2.Retrofit;

public class WorkTicketsInfoActivity extends AppCompatActivity {

    private DrawableHorizontalButton btCallPhone, btLocation;
    private NodeProcessBar nodeProcessBar;
    private TextView tvContact, tvTicketStatus, tvCustomerName, tvAddressValue, tvPhone, tvMsg, tvProcessCreateTime, tvUseTime;
    private String phone;
    private Button btCommit;
    private final List<String> mapAppPkgName = ListUtil.of("com.baidu.BaiduMap", "com.tencent.map", "com.autonavi.minimap");
    private ViewPager2 viewPager2;
    private TabLayout tabLayout;
    private WorkTicket workTicket;
    private String ticketState;
    private Dialog loadingDialog;
    private Retrofit mRetrofit;
    private static final int SELECT_USER_ACTIVITY = 1;
    private static final int TICKET_RECEIPT_ACTIVITY = 2;
    private WorkOrderApi workOrderApi;
    private com.jsjosem.aftersales.databinding.ActivityWorkTicketsInfoBinding binding;
    private LinearLayout view;
    private StateAdapter stateAdapter;
    private Intent intent;
    private ImageView ivWorkBack;
    private TextView tvCreator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_work_tickets_info);
        binding = ActivityWorkTicketsInfoBinding.inflate(getLayoutInflater());
        view = binding.getRoot();
        initView();
        intent = getIntent();
        init();
        // 打电话
        callPhone();
        // 导航底部弹窗
        naviBottomDialog();
    }

    private void init() {
        String data = intent.getStringExtra("data");
        if (StrUtil.isNotBlank(data)) {
            workTicket = new Gson().fromJson(data, WorkTicket.class);
            initData();
        } else {
            long workId = intent.getLongExtra("workId", 0);
            if (workId == 0) {
                Toast.makeText(this, "工单不存在", Toast.LENGTH_SHORT).show();
                finish();
            }
            loadWorkInfoData(String.valueOf(workId));
        }
        ivWorkBack.setOnClickListener(v -> finish());
    }

    private void initViewPage() {
        stateAdapter.clearAllFragment();
        stateAdapter.addFragment(TicketInfoFragment.newInstance(workTicket));
        String ticketState = workTicket.getTicketState();
        // 只有已完成才有回单信息
        if (StrUtil.equals(ticketState, WorkOrderStatusEnum.COMPLETED.getDesc())) {
            // 回单信息
            stateAdapter.addFragment(ReceiptInfoFragment.newInstance(workTicket));
        }
        viewPager2.setOffscreenPageLimit(stateAdapter.getItemCount());
        viewPager2.setAdapter(stateAdapter);
        viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                View view = stateAdapter.getFragment(position).getView();
                if (Objects.isNull(view)) {
                    return;
                }
                ViewUtils.updatePagerHeightForChild(view, viewPager2);
            }
        });

        List<String> stateList = ListUtil.of("工单信息", "回执信息");
        new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> {
            String state = stateList.get(position);
            tab.setText(state);
        }).attach();
    }

    private void initData() {
        HashSet<Integer> selected = new HashSet<>();
        // 默认选中第一个
        selected.add(0);
        List<String> stateList = Arrays.stream(WorkOrderStatusEnum.values()).map(WorkOrderStatusEnum::getDesc).collect(Collectors.toList());
        ticketState = workTicket.getTicketState();
        for (int i = 0; i < stateList.size(); i++) {
            selected.add(i);
            if (StrUtil.equals(stateList.get(i), ticketState)) {
                break;
            }
        }
        nodeProcessBar.show(stateList, selected);
        tvTicketStatus.setText(ticketState);
        tvContact.setText(workTicket.getOriginalTicket().getmContactName());
        tvCustomerName.setText(workTicket.getCustomerName());
        tvAddressValue.setText(workTicket.getAddress());
        phone = workTicket.getOriginalTicket().getmContactPhone();

        tvPhone.setText(phone);
        List<OperationLogResponse> logs = workTicket.getOriginalTicket().getmLogs();
        String log;
        if (CollUtil.isNotEmpty(logs)) {
            OperationLogResponse operationLogResponse = logs.get(logs.size() - 1);
            tvCreator.setText(String.format("[%s]", operationLogResponse.getCreator()));
            log = operationLogResponse.getAction();
            tvProcessCreateTime.setText(operationLogResponse.getCreateTime());
        } else {
            log = "暂无信息";
        }
        switch (ticketState) {
            case "已创建":
                tvUseTime.setText("请指派工单");
                break;
            case "已指派":
                List<WorkOrderHistoryResponse> historyResponses = workTicket.getOriginalTicket().getmHistories();
                LocalDateTime now=LocalDateTime.now();
                now=now.plusHours(8);
                String createTimeFormat;
                if (workTicket.getOriginalTicket().getmHistories().get(0).getStatus().equals("已指派")) {
                    createTimeFormat = historyResponses.get(0).getCreateTimeFormat();

                }else{
                    createTimeFormat = historyResponses.get(1).getCreateTimeFormat();
                }
                LocalDateTime createTime = DateUtil.parseLocalDateTime(createTimeFormat);
                Duration between = Duration.between(createTime, now);
                long minutes = between.toMinutes() % 60;
                long honers = (between.toMinutes() / 60) % 24;
                long day = (between.toMinutes() / 60) / 24;
                String date=day + "天" + honers + "小时" + minutes + "分钟";
                tvUseTime.setText(String.format("指派用时: %s", date));
                break;
            case "已接受":
                if (workTicket.getOriginalTicket().getmHistories().get(0).getStatus().equals("已指派")) {
                    tvUseTime.setText(String.format("接单用时: %s", getBetweenTime(0, 1)));

                } else {
                    tvUseTime.setText(String.format("接单用时: %s", getBetweenTime(1, 2)));
                }
                break;
            case "已开始":
                if (workTicket.getOriginalTicket().getmHistories().get(0).getStatus().equals("已指派")) {
                    tvUseTime.setText(String.format("开始用时: %s", getBetweenTime(1, 2)));

                } else {
                    tvUseTime.setText(String.format("开始用时: %s", getBetweenTime(2, 3)));
                }
                break;
            case "已完成":
                if (workTicket.getOriginalTicket().getmHistories().get(0).getStatus().equals("已指派")) {
                    tvUseTime.setText(String.format("完成用时: %s", getBetweenTime(2, 3)));

                } else {
                    tvUseTime.setText(String.format("完成用时: %s", getBetweenTime(3, 4)));
                }
        }

        tvMsg.setText(log);
        initViewPage();
        initProcessBtAndCreateBt();
    }

    private void naviBottomDialog() {
        btLocation.setOnClickListener(view -> {
            List<AppInfo> appList = getInstalledAppList(this, mapAppPkgName);
            if (CollUtil.isEmpty(appList)) {
                Toast.makeText(this, "未安装常用地图软件,无法导航,目前支持: 高德地图导航,百度地图导航,腾讯地图导航", Toast.LENGTH_LONG).show();
                return;
            }
            String targetAddress = tvAddressValue.getText().toString();
            startNavi(this, appList, targetAddress);
        });
    }

    private void callPhone() {
        btCallPhone.setOnClickListener(view -> {
            if (StrUtil.isBlank(phone)) {
                Toast.makeText(this, "没有电话号码", Toast.LENGTH_SHORT).show();
                return;
            }
            Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phone));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        });
    }

    private void initView() {
        mRetrofit = RetrofitClient.getInstance();
        workOrderApi = mRetrofit.create(WorkOrderApi.class);
        nodeProcessBar = findViewById(R.id.nodeProcessBar);
        tvTicketStatus = findViewById(R.id.ticketStatus);
        tvCustomerName = findViewById(R.id.customerName);
        tvCreator = findViewById(R.id.tv_creator);
        tvAddressValue = findViewById(R.id.addressValue);
        btCallPhone = findViewById(R.id.callPhoneBt);
        btLocation = findViewById(R.id.locationBt);
        tvContact = findViewById(R.id.contactValue);
        tvPhone = findViewById(R.id.tv_phone);
        viewPager2 = findViewById(R.id.ticketInfoViewPage);
        tabLayout = findViewById(R.id.ticketInfoTabLayout);
        ivWorkBack = findViewById(R.id.iv_work_back);
        tvMsg = findViewById(R.id.msgTv);
        tvProcessCreateTime = findViewById(R.id.processCreateTimeTv);
        btCommit = findViewById(R.id.bt_commit);
        tvUseTime = findViewById(R.id.useTime);
        stateAdapter = new StateAdapter(this);
    }

    private void initProcessBtAndCreateBt() {
        WorkOrderStatusEnum stateEnum = WorkOrderStatusEnum.getEnum(ticketState);
        if (stateEnum == null) {
            Toast.makeText(this, "状态" + ticketState + "不存在", Toast.LENGTH_LONG).show();
            return;
        }
        switch (stateEnum) {
            case CREATED: // 已创建
                btCommit.setText("分配");
                btCommit.setOnClickListener(view -> {
                    Intent intent = new Intent(this, SelectUserActivity.class);
                    intent.putExtra("workId", workTicket.getId().toString());
                    startActivityForResult(intent, SELECT_USER_ACTIVITY);
                });
                break;
            case ASSIGNED: // 已指派
                btCommit.setText("接单");
                btCommit.setOnClickListener(view -> {
                    selectDate();
                });
                break;
            case ACCEPTED: // 已接受
                btCommit.setText("开始工作");
                btCommit.setOnClickListener(view -> {
                    ConfirmDialog confirmDialog = new ConfirmDialog(this, () -> {
                        loadingShow();
                        Call<BaseResponse<Void>> startCall = workOrderApi.start(workTicket.getId().toString());
                        AsyncRequest<BaseResponse<Void>> request = new AsyncRequest<>();
                        request.sendRequest(startCall, (res) -> {
                            loadingDialog.dismiss();
                            loadWorkInfoData(workTicket.getId().toString());
                        }, errMsg -> {
                            loadingDialog.dismiss();
                            Toast.makeText(this, errMsg.toString(), Toast.LENGTH_SHORT).show();
                        });
                    });
                    confirmDialog.setTitle("提示");
                    confirmDialog.setContent("确定开始工作吗？");
                });
                break;
            case STARTED:
                btCommit.setText("完成工作");
                btCommit.setOnClickListener(view -> {
                    ConfirmDialog confirmDialog = new ConfirmDialog(this, () -> {
                        Intent intent = new Intent(this, TicketReceiptActivity.class);
                        intent.putExtra("workId", workTicket.getId().toString());
                        startActivityForResult(intent, TICKET_RECEIPT_ACTIVITY);
                    });
                    confirmDialog.setTitle("提示");
                    confirmDialog.setContent("确定完成工作并进行回执确认吗？");
                });
                break;
            case COMPLETED:
                // 已完成 隐藏提交按钮
                btCommit.setVisibility(View.GONE);
            default:
        }
    }

    private void selectDate() {
        SelectDateDialog selectDateDialog = new SelectDateDialog(this, date -> {
            loadingShow();
            AcceptWorkOrderRequest acceptWorkOrderRequest = new AcceptWorkOrderRequest();
            acceptWorkOrderRequest.setmPlatAt(date);
            Call<BaseResponse<Void>> acceptCall = workOrderApi.accept(workTicket.getId().toString(), acceptWorkOrderRequest);
            AsyncRequest<BaseResponse<Void>> asyncRequest = new AsyncRequest<>();
            asyncRequest.sendRequest(acceptCall, (res) -> {
                loadingDialog.dismiss();
                Toast.makeText(this, res.getMsg(), Toast.LENGTH_SHORT).show();
                loadWorkInfoData(workTicket.getId().toString());
            }, errMsg -> {
                loadingDialog.dismiss();
                Toast.makeText(this, errMsg.toString(), Toast.LENGTH_SHORT).show();
            });
        });
        selectDateDialog.show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == SELECT_USER_ACTIVITY && resultCode == RESULT_OK) {
            String workId = data.getStringExtra("workId");
            loadWorkInfoData(workId);
        }
        if (requestCode == TICKET_RECEIPT_ACTIVITY && resultCode == RESULT_OK) {
            String workId = data.getStringExtra("workId");
            loadWorkInfoData(workId);
        }
    }

    public void loadingShow() {
        loadingDialog = new Dialog(this, R.style.normal_dialog_style);
        View loadingView = View.inflate(this, R.layout.dialog_loading, null);
        loadingDialog.setContentView(loadingView);
        //使得点击对话框外部不消失对话框
        loadingDialog.setCanceledOnTouchOutside(false);
        AVLoadingIndicatorView avi = loadingView.findViewById(R.id.avi);
        avi.show();
        loadingDialog.show();
    }

    private void loadWorkInfoData(String workId) {
        loadingShow();
        Call<BaseResponse<WorkOrderResponse>> workInfoCall = workOrderApi.getById(workId);
        AsyncRequest<BaseResponse<WorkOrderResponse>> request = new AsyncRequest<>();
        request.sendRequest(workInfoCall, (res) -> {
            WorkOrderResponse workOrder = res.getData();
            workTicket = new WorkTicket();
            workTicket.setAddress(workOrder.getmAddress());
            workTicket.setTicketType(workOrder.getmType());
            workTicket.setTicketState(workOrder.getmStatus());
            workTicket.setTicketCode(workOrder.getmWoNumber());
            workTicket.setId(workOrder.getmId());
            workTicket.setScheduleTime(workOrder.getmPlanAt());
            List<UserInfoResponse> userInfoResponses = workOrder.getmUsers();
            for (int i = 0; i < userInfoResponses.size(); i++) {
                if (userInfoResponses.get(i).getIsMaster() == 1) {
                    workTicket.setHandlers(userInfoResponses.get(i).getUser().getRealname());
                }
            }
            workTicket.setCustomerName(workOrder.getmContactName());
            workTicket.setOriginalTicket(workOrder);
            initData();
            loadingDialog.dismiss();
        }, errMsg -> {
            loadingDialog.dismiss();
            Toast.makeText(this, errMsg.toString(), Toast.LENGTH_SHORT).show();
        });
    }

    private String getBetweenTime(int start, int end) {
        List<WorkOrderHistoryResponse> historyResponses = workTicket.getOriginalTicket().getmHistories();
        String createTimeFormat = historyResponses.get(start).getCreateTimeFormat();
        String acceptTimeFormat = historyResponses.get(end).getCreateTimeFormat();
        LocalDateTime createTime = DateUtil.parseLocalDateTime(createTimeFormat);
        LocalDateTime acceptTime = DateUtil.parseLocalDateTime(acceptTimeFormat);
        Duration between = Duration.between(createTime, acceptTime);
        long minutes = between.toMinutes() % 60;
        long honers = (between.toMinutes() / 60) % 24;
        long day = (between.toMinutes() / 60) / 24;
        return day + "天" + honers + "小时" + minutes + "分钟";
    }
}